home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / mint96sb.zoo / src / syscall.spp < prev    next >
Encoding:
Text File  |  1992-10-06  |  11.2 KB  |  389 lines

  1. %include "magic.i"
  2. ;
  3. ; syscall: interface for system calls. The following entry points are
  4. ;    defined:
  5. ; _mint_bios:  entry point for the BIOS calls (trap #13)
  6. ; _mint_xbios: entry point for XBIOS calls (trap #14)
  7. ; _mint_dos:   entry point for GEMDOS calls (trap #1)
  8. ; _sig_return: user signal handlers return to this routine (see signal.c)
  9. ;              it is responsible for restoring the kernel's old context
  10. ;              via the Psigreturn() system call
  11. ; _lineA0:     calls the line A initialize routine
  12. ; _call_aes:   calls the GEM AES
  13. ; _callout:    calls an external function, after first saving all registers,
  14. ;              and restores the registers afterward
  15. ;
  16. ; external variables referenced:
  17. ; _bios_tab, _bios_max:
  18. ;    table of entry points for BIOS routines, max # of routine
  19. ; _xbios_tab, _xbios_max:
  20. ;    ditto for XBIOS
  21. ; _dos_tab, _dos_max:
  22. ;    ditto for GEMDOS
  23. ; _curproc:
  24. ;    pointer to current process table entry, and hence to save area for
  25. ;    context (this is always the first entry in the PROC table).
  26. ; _valid_return:
  27. ;    used to indicate to the kernel that a valid return from user mode
  28. ;    is taking place
  29. ;
  30. ; _bconbuf, _bconbsiz, _bconbdev:
  31. ;    256 byte buffer for Bconout() output. If _bconbsiz is non-zero,
  32. ;    there are that many bytes in _bconbuf waiting to be flushed. The
  33. ;    output is for device _bconbdev.
  34. ;
  35. ; The C function enter_kernel() is called on entry to the kernel, and the
  36. ; function leave_kernel() is called on exit. These functions are responsible
  37. ; for saving and restoring the various trap vectors, so that MiNT can trap
  38. ; out to TOS directly, but programs can only trap to MiNT.
  39. ;
  40. ; we also call certain BIOS functions directly if these are known not to
  41. ; require saving/restoring of context
  42. ;
  43.     TEXT
  44.     
  45.     XDEF    _mint_bios,_mint_xbios
  46.     XDEF    _mint_dos
  47.     XREF    _build_context
  48.     XREF    _restore_context
  49.     XREF    _proc_clock        ; controls process' allocation of CPU time
  50.     XREF    _enter_kernel
  51.     XREF    _leave_kernel
  52.     XREF    _preempt
  53.  
  54.     XREF    _curproc
  55.     XREF    _bios_tab,_bios_max
  56.     XREF    _xbios_tab,_xbios_max
  57.     XREF    _dos_tab,_dos_max
  58.  
  59.     XREF    _bconbuf,_bconbsiz,_bconbdev
  60.     XREF    _bflush
  61.  
  62.     XREF    _ubconstat,_do_bconin,_ubcostat,_kbshift
  63.     
  64. _mint_dos:
  65.     clr.w    -(sp)            ; no frame format needed
  66.     move.l    _curproc,d0
  67.     addq.l    #4,d0
  68.     move.l    d0,-(sp)        ; push pointer to syscall context save
  69.     jsr    _build_context
  70.     move.l    #_dos_tab,a5        ; set syscall_tab
  71.     move.w    _dos_max,d5        ; set syscall_max
  72. ;
  73. ; copy parameters onto process stack. a0 and a1 were set by _build_context
  74. ;
  75.  
  76.     move.l    _curproc,a0
  77.     move.l    (a0),sp            ; this puts us in our private stack
  78.     move.l    24(a1),-(sp)        ; a1 was set by build_context
  79.     move.l    20(a1),-(sp)
  80.     move.l    16(a1),-(sp)
  81.     move.l    12(a1),-(sp)
  82.     move.l    8(a1),-(sp)
  83.     move.l    4(a1),-(sp)
  84.     move.l    (a1),-(sp)
  85.     jsr    _enter_kernel        ; set up vectors appropriately
  86.     bra    _syscall
  87.  
  88. _mint_xbios:
  89.     clr.w    -(sp)            ; no frame format needed
  90.     move.l    _curproc,d0
  91.     addq.l    #4,d0
  92.     move.l    d0,-(sp)        ; push pointer to syscall context save
  93.     jsr    _build_context
  94.     move.l    #_xbios_tab,a5        ; set syscall_tab
  95.     move.w    _xbios_max,d5        ; set syscall_max
  96. ;
  97. ; copy parameters onto process stack. a0 and a1 were set by _build_context
  98. ;
  99.  
  100.     move.l    _curproc,a0
  101.     move.l    (a0),sp            ; this puts us in our private stack
  102.     move.l    24(a1),-(sp)        ; a1 was set by build_context
  103.     move.l    20(a1),-(sp)
  104.     move.l    16(a1),-(sp)
  105.     move.l    12(a1),-(sp)
  106.     move.l    8(a1),-(sp)
  107.     move.l    4(a1),-(sp)
  108.     move.l    (a1),-(sp)
  109.     jsr    _enter_kernel        ; set up vectors appropriately
  110.     bra    _syscall
  111.  
  112. _mint_bios:
  113. ;
  114. ; Entering the kernel can be very expensive; so, we take a short-cut
  115. ; if possible -- we try some BIOS functions out, and if they
  116. ; succeed without blocking then we're done; otherwise, we go
  117. ; through the long procedure for entering the kernel
  118. ;
  119. ; These shortcuts aren't done when we're called in supervisor mode,
  120. ; because TOS uses very tiny stacks (smaller than we want); the
  121. ; shortcuts operate on the user-supplied ssp, whereas the "full"
  122. ; BIOS code works on our (private) system stack
  123. ;
  124.     jsr    _enter_kernel        ; set up BIOS vectors
  125.     btst    #5,(sp)            ; test for user/super mode
  126.     bne.s    L_bios            ; if super, goto L_bios
  127.     tst.w    _proc_clock        ; are we about to be preempted?
  128.     beq.s    L_bios
  129.  
  130.     move.l    usp,a1            ; user mode: args on user stack
  131. L_ubios:
  132.     move.w    (a1),d0            ; get command
  133.     cmp.w    #3,d0            ; Bconout?
  134.     beq    do_bconout        ; yes -- go do it
  135. ;
  136. ; most of the remaining functions require BIOS vectors to be properly
  137. ; set up
  138.     tst.w    _bconbsiz        ; is BIOS output waiting?
  139.     bne.s    L_bios            ; yes -- do regular code
  140.  
  141. ; test for various BIOS functions
  142.     cmp.w    #1,d0            ; Bconstat?
  143.     bne.s    L_00
  144.     move.w    2(a1),-(sp)        ; push arg
  145.     jsr    _ubconstat
  146. L_1out:
  147.     addq.l    #2,sp
  148. L_0out:
  149.     move.l    d0,-(sp)        ; save d0
  150.     ori.w    #$0700,sr        ; spl7()
  151.     jsr    _leave_kernel
  152.     move.l    (sp)+,d0        ; retrieve value to be returned
  153.     rte                ; return to user
  154. L_00:
  155.     cmp.w    #2,d0            ; Bconin?
  156.     bne.s    L_01
  157.     move.w    2(a1),-(sp)        ; yes; push argument
  158.     jsr    _do_bconin
  159.     addq.l    #2,sp
  160.     cmp.w    #$dead,d0        ; would Bconin block?
  161.     bne.s    L_0out            ; no -- we're done
  162.     bra.s    L_bios            ; yes -- do the long stuff
  163. L_01:
  164.     cmp.w    #8,d0            ; Bcostat?
  165.     bne.s    L_02
  166.     move.w    2(a1),-(sp)        ; push device
  167.     jsr    _ubcostat        ; get status
  168.     bra.s    L_1out
  169. L_02:
  170.     cmp.w    #11,d0            ; Kbshift?
  171.     bne.s    L_bios
  172.     move.w    2(a1),-(sp)        ; push arg
  173.     jsr    _kbshift
  174.     bra.s    L_1out
  175.  
  176. L_bios:
  177.     clr.w    -(sp)            ; no frame format needed
  178.     move.l    _curproc,d0
  179.     addq.l    #4,d0
  180.     move.l    d0,-(sp)        ; push pointer to syscall context save
  181.     jsr    _build_context
  182.     move.l    #_bios_tab,a5        ; set syscall_tab
  183.     move.w    _bios_max,d5        ; set syscall_max
  184. ;
  185. ; copy parameters onto process stack. a0 and a1 were set by _build_context
  186. ;
  187.  
  188.     move.l    _curproc,a0
  189.     move.l    (a0),sp            ; this puts us in our private stack
  190.     move.l    24(a1),-(sp)        ; a1 was set by build_context
  191.     move.l    20(a1),-(sp)
  192.     move.l    16(a1),-(sp)
  193.     move.l    12(a1),-(sp)
  194.     move.l    8(a1),-(sp)
  195.     move.l    4(a1),-(sp)
  196.     move.l    (a1),-(sp)
  197.  
  198. _syscall:
  199. ;
  200. ; check here to see if we need to flush the Bconout() buffer
  201. ;
  202.     tst.w    _bconbsiz        ; characters in buffer?
  203.     beq.s    L_noflush        ; no: OK to proceed
  204. ;
  205. ; watch out, this could cause a context switch
  206. ;
  207.     jsr    _bflush            ; flush the buffer
  208.  
  209. L_noflush:
  210. ;
  211. ; figure out which routine to call
  212. ;
  213.     move.w    (sp),d0
  214.     cmp.w    #-1,d0            ; trapping with -1 means return
  215.     bne.s    check_max        ; the corresponding system table
  216.     move.l    a5,d0
  217.     bra.s    out
  218. check_max:
  219.     cmp.w    d5,d0
  220.     bge.s    error
  221.     add.w    d0,d0
  222.     add.w    d0,d0            ; multiply by 4
  223.     move.l    0(a5,d0.w),d0        ; d0 = syscall_tab[d0]
  224.     beq.s    error            ; null entry means invalid call
  225.     addq.l    #2,sp            ; pop function number off stack
  226.     move.l    d0,a0
  227.     jsr    (a0)            ; go do the call
  228. out:
  229.     move.l    _curproc,a0
  230.     move.l    d0,P_SYSCTXT+C_D0(a0)    ; set d0 in the saved context
  231.     move.w    P_SYSCTXT+C_SR(a0),d0    ; get saved status register
  232.     
  233.     tst.l    P_PTRACER(a0)        ; check curproc->ptracer, if not set
  234.     beq.s    notrace            ; then no pending trace; this ensures
  235.     move.w    d0,d1            ; we work with non-MiNT debuggers
  236.     and.w    #$c000,d1        ; are either of the trace bits set
  237.     sne    P_SYSCTXT+C_PTRACE(a0)    ; mark as trace pending/not
  238. notrace:
  239.     tst.w    _proc_clock        ; has process exceeded time slice?
  240.     bne.s    nosleep            ; no -- continue
  241.     btst    #13,d0            ; caller in supervisor mode?
  242.     bne.s    nosleep            ; yes -- don't interrupt
  243.     tst.w    ($43e).w        ; test floppy disk lock variable
  244.     bne.s    nosleep            ; if locked, can't switch
  245. sleep:
  246.     jsr    _preempt        ; does a sleep(READY_Q)
  247. nosleep:
  248.     ori.w    #$0700,sr        ; spl7()
  249.     jsr    _leave_kernel        ; restore vectors
  250.     move.l    _curproc,a0
  251.     pea    4(a0)
  252.     jsr    _restore_context    ; never returns
  253.  
  254. ;
  255. ; we handle errors by calling through to GEMDOS or the BIOS/XBIOS,
  256. ; as appropriate, and letting them handle it -- that way, if the underlying
  257. ; system has functions we don't know about, they still work
  258. ; to figure out which trap we have to call, we use the system call
  259. ; table placed in a5 earlier
  260.  
  261. error:
  262.     cmp.l    #_xbios_tab,a5
  263.     bne.s    maybe_bios
  264.     trap    #14
  265.     bra.s    out
  266. maybe_bios:
  267.     cmp.l    #_dos_tab,a5
  268.     beq.s    trap_1
  269.     trap    #13
  270.     bra.s    out
  271. trap_1:
  272.     trap    #1
  273.     bra.s    out
  274.  
  275. ;
  276. ; sig_return: user signal handlers return to us. At that point, the
  277. ; stack looks like this:
  278. ;    (sp)      (long) signal number -- was a parameter for user routine
  279. ;
  280.     XDEF    _sig_return
  281.     XREF    _valid_return
  282. _sig_return:
  283.     addq.l    #4,sp            ; pop signal number
  284.     move.w    #$11a,-(sp)        ; Psigreturn() system call
  285.     move.w    #1,_valid_return    ; tell kernel it's us!
  286.     trap    #1
  287. ; we had better not come back; if we did, something terrible
  288. ; happened, and we might as well terminate
  289.     move.w    #-998,-(sp)
  290.     move.w    #$4c,-(sp)        ; Pterm()
  291.     trap    #1
  292. ;
  293. ; bconout special code: on entry, a1 points to the stack the user
  294. ; was using. If possible, we just buffer the output until later.
  295. ;
  296.  
  297. do_bconout:
  298.     tst.w    _bconbdev        ; is BIOS buffering on?
  299.     bmi    L_bios            ; no buffering -- skip this code
  300.     move.w    2(a1),d0        ; what device is this for?
  301.     beq    L_bios            ; don't buffer the printer
  302.     cmp.w    _bconbdev,d0        ; same device as is buffered?
  303.     bne.s    new_dev            ; no -- maybe we can't do this
  304. put_buf:
  305.     move.w    4(a1),d0        ; get the character to output
  306.     move.w    _bconbsiz,d1        ; get index into buffer table
  307.     cmp.w    #255,d1            ; buffer full?
  308.     beq    L_bios            ; yes -- flush it out
  309.     lea    _bconbuf,a0
  310.     add.w    d1,a0
  311.     move.b    d0,(a0)            ; store the character
  312.     addq.w    #1,d1
  313.     move.w    d1,_bconbsiz
  314.     jsr    _leave_kernel        ; restore vectors
  315.     moveq.l    #-1,d0            ; return character output OK
  316.     rte
  317.  
  318. new_dev:
  319.     tst.w    _bconbsiz        ; characters already in buffer?
  320.     bne    L_bios            ; yes: we can't buffer this one
  321.     move.w    d0,_bconbdev        ; no: OK, we have a new device
  322.     bra.s    put_buf
  323.  
  324. ;
  325. ; _lineA0: MiNT calls this to get the address of the line A variables
  326. ;
  327.     XDEF    _lineA0
  328. _lineA0:
  329.     movem.l    d2/a2,-(sp)    ; save scratch registers
  330.     dc.w    $a000        ; call the line A initialization routine
  331.     movem.l    (sp)+,d2/a2
  332.     rts
  333.  
  334. ;
  335. ; _call_aes: calls the GEM AES, using the control block passed as
  336. ;            a parameter. Used only for doing appl_init(), to see
  337. ;         if the AES is active yet
  338. ;
  339.     XDEF    _call_aes
  340. _call_aes:
  341.     move.l    4(sp),d1    ; fetch pointer to parameter block
  342.     move.w    #$c8,d0        ; magic number for AES
  343.     movem.l    d2/a2,-(sp)    ; save scratch registers
  344.     trap    #2
  345.     movem.l    (sp)+,d2/a2
  346.     rts
  347.  
  348. ;
  349. ; _callout: Call an external function, passing <32 bytes of arguments,
  350. ; and return the value from the function. NOTE: we must be careful
  351. ; to save all registers here!
  352. ;
  353.     XDEF    _callout
  354.     XDEF    _callout1
  355.     XDEF    _callout2
  356. ;
  357. ; _callout is the general purpose one
  358. ;
  359. _callout:
  360.     lea    8(sp),a0        ; pointer to args
  361.     move.l    4(sp),a1        ; pointer to pointer to function
  362.     movem.l    d2-d7/a2-a6,-(sp)    ; save registers
  363.     movem.l    (a0),d0-d7        ; copy parameters
  364.     lea    -32(sp),sp        ; NOTE: movem.l auto-decrement
  365.     movem.l    d0-d7,(sp)        ;    changes the order of things
  366.     jsr    (a1)            ; go do it
  367.     lea    32(sp),sp
  368.     movem.l    (sp)+,d2-d7/a2-a6    ; restore reggies
  369.     rts
  370. ;
  371. ; _callout2 and _callout1 are for functions with just 1 or
  372. ; 2 16 bit parameters. We cheat and use the same code for
  373. ; both, since passing 32 bits isn't much more expensive than
  374. ; passing 16 bits (and since the called function will just
  375. ; ignore any extra arg)
  376. ;
  377.  
  378. _callout1:
  379. _callout2:
  380.     movem.l    4(sp),a0/a1        ; get function ptr & args
  381.     movem.l    d2-d7/a2-a6,-(sp)    ; save reggies
  382.     move.l    a1,-(sp)        ; push args
  383.     jsr    (a0)            ; do function
  384.     addq.l    #4,sp
  385.     movem.l    (sp)+,d2-d7/a2-a6    ; restore reggies
  386.     rts
  387.  
  388.     END
  389.